<template>
  <view class="container">
    <!-- 1. 相机页面 (已重构) -->
    <view v-if="pageState === 'camera'" class="camera-container">
      <!-- 1.1 相机预览区域 -->
      <view class="camera-wrapper">
        <!-- 移除了 `v-if="!singlePhotoPath"` 判断，因为在 'camera' 状态下它永远为 true -->
        <canvas v-show="showCamera" ref="canvasElement" class="camera-canvas"></canvas>
        <view class="camera-prompt">
          <text class="prompt-text">{{ currentTextTips }}</text>
        </view>
        <image class="guide-image" :src="currentOverlay" />

        <view v-if="canSkip" class="skip-prompt-box" @click="skipOptionalPhotos">
          <text>{{ $t("zhen.skip_optional_photos") }}</text>
          <text class="skip-highlight">{{ $t("zhen.skip") }}</text>
        </view>
      </view>

      <!-- 1.2 底部控制区域 -->
      <view class="bottom-controls">
        <view v-if="cameraSource === 'acupoint'" class="part-selector">
          <scroll-view scroll-x="true" class="scroll-view" show-scrollbar="false">
            <view
              v-for="(part, index) in bodyParts"
              :key="part.id"
              class="part-item"
              :class="{ active: active_id === part.id }"
              @click="selectPart(index, part.id)"
              >{{ part.body_name }}</view
            >
          </scroll-view>
        </view>
        <view class="action-buttons">
          <view class="shutter-button-wrapper center-shutter" @click="takePhoto" :class="{ disabled: !showCamera }">
            <view class="shutter-button"></view>
          </view>
          <view class="button-wrapper right-switch" @click="switchCamera">
            <image src="/static/icons/phone.png" class="icon-placeholder" mode="aspectFit"></image>
            <text class="btn-text">{{ t("zhen.switch") }}</text>
          </view>
        </view>
      </view>
    </view>

    <!-- [新增] 2. 单张照片确认页面 -->
    <view v-else-if="pageState === 'singleConfirm'" class="camera-container">
      <!-- 2.1 照片预览区域 -->
      <view class="camera-wrapper">
        <image :src="singlePhotoPath" class="preview-image" mode="heightFix" />
      </view>
      <!-- 2.2 底部控制区域 -->
      <view class="bottom-controls">
        <view class="confirm-actions">
          <view class="button-wrapper" @click="retake"
            ><text class="btn-text">{{ t("zhen.retake") }}</text></view
          >
          <view class="button-wrapper" @click="confirm"
            ><text class="btn-text primary">{{ t("zhen.confirm") }}</text></view
          >
        </view>
      </view>
    </view>

    <!-- 3. 多照片确认页面 -->
    <view v-else-if="pageState === 'multiConfirm'" class="confirm-page-container">
      <view class="confirm-page-header">
        <text class="header-title">{{ pageTitle }}</text>
      </view>
      <scroll-view scroll-y class="confirm-scroll-view">
        <view class="scroll-content-wrapper">
          <view v-for="(photo, index) in capturedPhotos" :key="index">
            <div v-if="photo.path" class="photo-item">
              <text class="photo-label">{{ currentWorkflow.steps[index].label }}</text>
              <image :src="photo.path" class="photo-preview" mode="aspectFill"></image>
            </div>
          </view>
        </view>
      </scroll-view>
      <view class="confirm-page-footer">
        <button class="footer-btn retake-btn" :disabled="isPolling" @click="retakeMultiPhotos">
          {{ $t("zhen.retake_multi") }}
        </button>
        <button class="footer-btn confirm-btn" :loading="isPolling" :disabled="isPolling" @click="confirmMultiPhotos">
          {{ isPolling ? $t("zhen.analyzing") : $t("zhen.confirm_multi") }}
        </button>
      </view>
    </view>
    <view v-else-if="pageState === 'switch'"></view>
    <!-- 4. 问卷调查页面 -->
    <view v-else-if="pageState === 'questionnaire'" class="questionnaire-page">
      <view class="questionnaire-header">
        <view class="header-text">{{ $t("zhen.questionnaire_tip1") }}</view>
        <view class="header-text">{{ $t("zhen.questionnaire_tip2") }}</view>
      </view>

      <scroll-view scroll-y class="questionnaire-scroll">
        <view class="question-list" :class="{ answering: isAnswering }">
          <view v-for="question in questionnaireData.questions" :key="question.subjectId" class="question-card">
            <view class="question-title-wrapper">
              <text class="question-title">{{ question.subjectTitle }}</text>
            </view>
            <view class="answer-options">
              <template v-if="question.subjectType === 0">
                <input
                  v-model="answers[question.subjectId]"
                  class="age-input"
                  type="number"
                  :placeholder="question.answer[0].answerTitle"
                  @blur="handleAgeInput(question.subjectId)"
                />
              </template>

              <template v-if="question.subjectType === 1">
                <view
                  v-for="option in question.answer"
                  :key="option.answerCode"
                  class="answer-btn"
                  :class="{ active: answers[question.subjectId] === option.answerCode }"
                  @click="selectAnswer(question.subjectId, option.answerCode)"
                >
                  {{ option.answerTitle }}
                </view>
              </template>
            </view>
          </view>
        </view>
      </scroll-view>
    </view>

    <!-- 5. 结果展示页面 -->
    <view v-else>
      <tongue-results-page v-if="cameraSource === 'tongue'" :result-data="analysisResult" @restart="restart" />
      <face-results-page v-if="cameraSource === 'face'" :result-data="analysisResult" @restart="restart" />
      <results-page
        v-else
        :photo-path="analysisResult.picUrl"
        :acupoint-list="analysisResult.acupointList"
        :link-to="analysisResult.linkTo"
        @restart="restart"
      />
    </view>
  </view>
</template>

<script>
import ResultsPage from "./ResultsPage.vue";
import TongueResultsPage from "./TongueResultsPage.vue";
import FaceResultsPage from "./FaceResultsPage.vue";
import { upload } from "@/utils/request.js";
import { useI18n } from "vue-i18n";
import {
  getpartlist,
  createAcupoint,
  checkStatus,
  getResult,
  createTonguet,
  checkTongueStatus,
  getTongueResult,
  createFaceDiagnosis,
  answerQuestion,
  answerTongueQuestion,
  getFinalFaceResult,
} from "@/api/acupoint.js";
import { useUserStore } from "@/store/user.js";
import { uni } from "@dcloudio/uni-h5";
// import VConsole from "vconsole";
export default {
  components: {
    ResultsPage,
    TongueResultsPage,
    FaceResultsPage,
  },
  data() {
    return {
      // --- 页面状态管理 ---
      // [MODIFIED] 新增 'singleConfirm' 状态
      pageState: "camera", // 'camera', 'singleConfirm', 'multiConfirm', 'questionnaire', 'results',switch
      cameraSource: "acupoint", // 'acupoint', 'tongue', 'face'

      // --- 相机核心 ---
      showCamera: false,
      isFrontCamera: false,
      stream: null,
      videoElement: null,
      canvasContext: null,
      animationFrameId: null,
      screenWidth: 0,
      screenHeight: 0,

      // --- 单张照片工作流 (穴位识别) ---
      singlePhotoPath: "", // 存储单张照片的临时路径
      bodyParts: [],
      activePartIndex: 0,
      active_id: 0,

      // --- 问卷相关数据 ---
      questionnaireData: {
        faceId: null,
        id: null,
        questions: [],
      },
      answers: {},
      isAnswering: false,

      // --- 多步骤拍照工作流 ---
      // 只保留类型key，具体内容用computed
      photoWorkflowType: "tongue", // 或 'face'，实际用 this.cameraSource
      currentStepIndex: 0,
      capturedPhotos: [],

      // --- 结果与轮询 ---
      analysisResult: { picUrl: "", acupointList: [], linkTo: {} },
      appoint_no: null,
      pollCount: 0,
      maxPollCount: 2,
      interval: 2000,
      pollTimer: null,
      isPolling: false,
      pollingRetryCount: 0, //  轮询重试计数
    };
  },
  setup() {
    const { t } = useI18n();
    return { t };
  },
  computed: {
    canSkip() {
      return this.cameraSource === "face" && this.currentStepIndex > 0;
    },
    isMultiStepFlow() {
      return this.cameraSource === "tongue" || this.cameraSource === "face";
    },
    workflowConfig() {
      // 用于多语言的动态配置
      if (this.cameraSource === "tongue") {
        return {
          title: this.$t("zhen.workflow.tongue.title"),
          steps: [
            {
              label: this.$t("zhen.workflow.tongue.steps[0].label"),
              prompt: this.$t("zhen.workflow.tongue.steps[0].prompt"),
              overlay: "/static/overlays/01.png",
            },
            {
              label: this.$t("zhen.workflow.tongue.steps[1].label"),
              prompt: this.$t("zhen.workflow.tongue.steps[1].prompt"),
              overlay: "/static/overlays/tongue.png",
            },
          ],
        };
      } else if (this.cameraSource === "face") {
        return {
          title: this.$t("zhen.workflow.face.title"),
          steps: [
            {
              label: this.$t("zhen.workflow.face.steps[0].label"),
              prompt: this.$t("zhen.workflow.face.steps[0].prompt"),
              overlay: "/static/overlays/face_01.png",
            },
            {
              label: this.$t("zhen.workflow.face.steps[1].label"),
              prompt: this.$t("zhen.workflow.face.steps[1].prompt"),
              overlay: "/static/overlays/face_02.png",
            },
            {
              label: this.$t("zhen.workflow.face.steps[2].label"),
              prompt: this.$t("zhen.workflow.face.steps[2].prompt"),
              overlay: "/static/overlays/face_02.png",
            },
          ],
        };
      }
      return {};
    },
    currentWorkflow() {
      return this.workflowConfig;
    },
    currentStepConfig() {
      if (!this.isMultiStepFlow) return null;
      return this.workflowConfig.steps[this.currentStepIndex];
    },
    pageTitle() {
      return this.isMultiStepFlow ? this.workflowConfig.title : this.$t("acupoint.title");
    },
    currentTextTips() {
      if (this.isMultiStepFlow) {
        return this.currentStepConfig?.prompt || "";
      }
      return this.bodyParts[this.activePartIndex]?.remark || this.$t("zhen.acupoint_photo_tip");
    },
    currentOverlay() {
      if (this.isMultiStepFlow) {
        return this.currentStepConfig?.overlay || "";
      }
      return this.bodyParts[this.activePartIndex]?.img_url || "";
    },
    userStore() {
      return useUserStore();
    },
    userInfo() {
      return this.userStore.userInfo;
    },
    // 用于判断是否所有问题都已回答
    areAllQuestionsAnswered() {
      const questions = this.questionnaireData.questions;
      if (!questions || questions.length === 0) {
        return false;
      }
      return questions.every((q) => {
        const answer = this.answers[q.subjectId];
        return answer !== null && answer !== undefined && String(answer).trim() !== "";
      });
    },
  },
  onLoad(options) {
    if (options && options.source) {
      this.cameraSource = options.source;
      // console.log('当前相机来源:', this.cameraSource)
    } else {
      // console.warn('未指定相机来源，将使用默认逻辑。')
    }
    this.initializeBasedOnSource();
    this.setNavTitle();
  },
  onReady() {
    if (this.pageState === "camera") {
      this.initCamera();
      // new VConsole();
    }
    this.setNavTitle();
  },
  onUnload() {
    this.stopCamera();
  },
  watch: {
    "$i18n.locale"() {
      this.setNavTitle();
    },
  },
  methods: {
    setNavTitle() {
      let key = "tongue.title";
      if (this.cameraSource === "acupoint") key = "acupoint.title";
      if (this.cameraSource === "face") key = "face.title";
      uni.setNavigationBarTitle({ title: this.$t(key) });
    },
    initializeBasedOnSource() {
      this.resetWorkflowState();
      if (this.cameraSource === "acupoint") {
        this.getpartListData();
      }
    },
    resetWorkflowState() {
      this.currentStepIndex = 0;
      this.capturedPhotos = [];
      this.singlePhotoPath = "";
      this.questionnaireData = { faceId: null, id: null, questions: [] };
      this.answers = {};
      this.isAnswering = false;
      this.isPolling = false;
      this.pollingRetryCount = 0; //重置重试计数
    },
    async getpartListData() {
      const res = await getpartlist();
      if (res.result && res.result.length > 0) {
        this.bodyParts = res.result;
        this.active_id = res.result[0].id;
      }
    },
    // ... (initCamera, startDrawing, getCanvasElement methods remain the same) ...
    async initCamera() {
      this.stopCamera();
      try {
        const rect = await new Promise((resolve) => {
          uni
            .createSelectorQuery()
            .in(this)
            .select(".camera-wrapper")
            .boundingClientRect((data) => {
              if (data) {
                this.screenWidth = data.width;
                this.screenHeight = data.height;
              } else {
                this.screenWidth = window.innerWidth;
                this.screenHeight = window.innerHeight;
                console.warn(this.$t("zhen.camera_wrapper_size_failed"));
              }
              resolve(data);
            })
            .exec();
        });

        const canvas = await this.getCanvasElement();
        if (!canvas) return;

        canvas.width = this.screenWidth;
        canvas.height = this.screenHeight;

        this.canvasContext = canvas.getContext("2d");
        this.videoElement = document.createElement("video");
        this.videoElement.setAttribute("playsinline", true);
        this.videoElement.muted = true;
        this.videoElement.autoplay = true;
        this.videoElement.style.display = "none";
        document.body.appendChild(this.videoElement);
        this.stream = await navigator.mediaDevices.getUserMedia({
          video: { facingMode: this.isFrontCamera ? "user" : "environment" },
        });
        this.videoElement.srcObject = this.stream;
        this.videoElement.onloadedmetadata = () => {
          this.videoElement.play();
          this.showCamera = true;
          this.startDrawing();
        };
      } catch (error) {
        console.error(this.$t("zhen.camera_start_failed"), error);
        uni.showModal({
          title: this.$t("zhen.camera_error"),
          content: this.$t("zhen.camera_error_content"),
          showCancel: false,
        });
      }
    },

    startDrawing() {
      if (!this.showCamera || !this.videoElement || !this.videoElement.videoWidth) {
        if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId);
        this.animationFrameId = null;
        return;
      }

      const ctx = this.canvasContext;
      const canvasWidth = this.screenWidth;
      const canvasHeight = this.screenHeight;

      // 获取视频的原始尺寸
      const videoWidth = this.videoElement.videoWidth;
      const videoHeight = this.videoElement.videoHeight;

      // 计算视频和Canvas的宽高比
      const videoRatio = videoWidth / videoHeight;
      const canvasRatio = canvasWidth / canvasHeight;

      let drawWidth, drawHeight, offsetX, offsetY;

      // 核心逻辑：计算如何绘制才能保持比例并填满Canvas
      if (videoRatio > canvasRatio) {
        // 视频比Canvas更宽：高度撑满，宽度裁剪
        drawHeight = canvasHeight;
        drawWidth = drawHeight * videoRatio;
        offsetX = (canvasWidth - drawWidth) / 2; // 水平居中
        offsetY = 0;
      } else {
        // 视频比Canvas更高（或比例相同）：宽度撑满，高度裁剪
        drawWidth = canvasWidth;
        drawHeight = drawWidth / videoRatio;
        offsetX = 0;
        offsetY = (canvasHeight - drawHeight) / 2; // 垂直居中
      }

      ctx.clearRect(0, 0, canvasWidth, canvasHeight);

      // 保存当前上下文状态
      ctx.save();

      if (this.isFrontCamera) {
        // 前置摄像头需要水平翻转
        ctx.translate(canvasWidth, 0);
        ctx.scale(-1, 1);
      }

      // 使用计算出的尺寸和偏移量进行绘制
      ctx.drawImage(this.videoElement, offsetX, offsetY, drawWidth, drawHeight);

      // 恢复到翻转前的状态
      ctx.restore();

      this.animationFrameId = requestAnimationFrame(this.startDrawing.bind(this));
    },
    getCanvasElement() {
      return new Promise((resolve) => {
        uni
          .createSelectorQuery()
          .in(this)
          .select(".camera-canvas")
          .node((res) => resolve(res ? res.node : null))
          .exec();
      });
    },
    async takePhoto() {
      // 1. 检查相机是否就绪
      if (!this.showCamera) {
        console.warn("Camera not ready, cannot take photo.");
        return;
      }

      // 2. 获取用户当前正在预览的那个 Canvas 元素
      //    我们用 async/await 来确保能拿到元素
      const canvasElement = await this.getCanvasElement();
      if (!canvasElement) {
        console.error("Failed to get the main canvas element for taking a photo.");
        uni.showToast({ title: this.$t("zhen.photo_take_failed"), icon: "none" });
        return;
      }

      // 3. 直接从这个可见的 Canvas 中导出图像数据
      //    这能保证捕获的图像与用户看到的预览完全一致
      const photoBase64 = canvasElement.toDataURL("image/jpeg", 0.9);

      // 4. 后续逻辑保持不变
      if (this.isMultiStepFlow) {
        // 多步骤流程
        this.capturedPhotos.push({ path: photoBase64 });
        this.currentStepIndex++;
        if (this.currentStepIndex >= this.currentWorkflow.steps.length) {
          this.stopCamera();
          this.pageState = "multiConfirm";
        } else {
          uni.showToast({
            title: this.$t("zhen.please_prepare", { label: this.currentStepConfig.label }),
            icon: "none",
            duration: 1500,
          });
        }
      } else {
        // 单张照片流程 (穴位识别)
        this.singlePhotoPath = photoBase64;
        this.stopCamera();
        this.pageState = "singleConfirm";
      }
    },
    selectPart(index, id) {
      this.activePartIndex = index;
      this.active_id = id;
    },
    stopCamera() {
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
        this.animationFrameId = null;
      }
      if (this.stream) {
        this.stream.getTracks().forEach((track) => track.stop());
        this.stream = null;
      }
      if (this.videoElement && document.body.contains(this.videoElement)) {
        document.body.removeChild(this.videoElement);
        this.videoElement = null;
      }
      this.showCamera = false;
    },
    // ...
    switchCamera() {
      this.pageState = "switch";
      // 1. 切换摄像头状态
      setTimeout(() => {
        this.pageState = "camera";
        this.isFrontCamera = !this.isFrontCamera;
        this.$nextTick(() => {
          this.initCamera();
        });
      }, 0);
    },
    // ...
    retake() {
      // 此方法现在用于单张照片重拍
      this.pageState = "camera";
      this.resetWorkflowState();
      this.$nextTick(() => this.initCamera());
    },
    // ... (confirm, checkStatusfn, getResultData, showPoseGuide methods remain the same) ...
    async confirm() {
      uni.showLoading({ title: this.$t("zhen.analyzing_smart"), mask: true });
      upload({
        url: "/api/v1/hospital/upload", // 你的后端上传路径
        filePath: this.singlePhotoPath,
        name: "file", // 后端接收字段
        showLoading: false,
        formData: {
          bizType: "user-avatar", // 业务参数，根据后端需求传
        },
      })
        .then((res) => {
          if (res.result && res.result.url) {
            const params = {
              acupoint_id: this.active_id,
              pic_url: res.result.url,
              user_id: this.userInfo.id,
            };
            createAcupoint(params).then((res) => {
              if (res.result && res.result.appoint_no) {
                this.appoint_no = res.result.appoint_no;
                this.checkStatusfn();
              } else {
                uni.hideLoading();
                uni.showToast({ title: res.message, icon: "none" });
              }
            });
          } else {
          }
        })
        .catch((err) => {
          console.error("上传失败", err);
        });
    },
    async getResultData() {
      try {
        const response = await getResult(this.appoint_no);
        if (response.code === 200 && response.result) {
          const resultsData = response.result;
          this.analysisResult = {
            picUrl: resultsData.pic_url,
            acupointList: resultsData.acupointList.map((point) => ({
              ...point,
              xaxis: Number(point.x_axis),
              yaxis: Number(point.y_axis),
            })),
            linkTo: {
              shoppingMallAppId: resultsData.shoppingMallAppId,
              shoppingMallUrl: resultsData.shoppingMallUrl,
            },
          };
          this.pageState = "results";
        } else {
          throw new Error(response.message || "分析服务出错，请稍后重试");
        }
      } catch (error) {
        uni.showToast({ title: error.message, icon: "none" });
      } finally {
        uni.hideLoading();
      }
    },
    async checkStatusfn() {
      if (this.pollingRetryCount === 0) {
        this.pollCount = 0; // 初次轮询时重置计数
      }
      clearTimeout(this.pollTimer);
      const loop = async () => {
        try {
          const res = await checkStatus(this.appoint_no);

          if (res.result && res.result.status === "000") {
            clearTimeout(this.pollTimer);
            this.pollTimer = null;
            this.pollingRetryCount = 0; // 成功后重置重试计数
            this.getResultData();
            return;
          }
          if (res.result && res.result.status === "101") {
            uni.showToast({ title: res.result.msg, icon: "none" });
            clearTimeout(this.pollTimer);
            this.pollTimer = null;
            this.pollingRetryCount = 0; // 失败后重置重试计数
            return;
          }

          this.pollCount++;
          if (this.pollCount >= this.maxPollCount) {
            clearTimeout(this.pollTimer);
            this.pollTimer = null;
            uni.hideLoading(); // 模态框前隐藏加载
            this.isPolling = false; // 按钮状态重置
            if (this.pollingRetryCount >= 1) {
              uni.hideLoading();
              uni.showModal({
                title: this.$t("common.confirm"),
                content: this.$t("zhen.analysis_still_in_progress"),
                showCancel: false, // 关键：隐藏取消按钮
                confirmText: this.$t("zhen.back_to_home"),
                success: (res) => {
                  if (res.confirm) {
                    // 用户点击“知道了”，返回首页
                    uni.reLaunch({ url: "/pages/index/index" });
                  }
                },
                fail: () => {
                  uni.reLaunch({ url: "/pages/index/index" });
                },
              });
            } else {
              // [ORIGINAL] 这是第一次超时，显示有两个选项的模态框
              uni.showModal({
                title: this.$t("common.confirm"),
                content: this.$t("zhen.analysis_timeout"),
                confirmText: this.$t("zhen.continue_waiting"),
                cancelText: this.$t("zhen.check_later"),
                success: (res) => {
                  if (res.confirm) {
                    // 用户选择“继续等待”
                    this.pollingRetryCount++; // 增加重试计数
                    this.pollCount = 0; // 重置当前轮询次数
                    this.isPolling = true; // 重新禁用按钮
                    uni.showLoading({ mask: true });
                    this.pollTimer = setTimeout(loop, this.interval); // 继续轮询
                  } else if (res.cancel) {
                    // 用户选择“稍后去历史记录查看”
                    uni.reLaunch({ url: "/pages/index/index" }); // 返回首页
                  }
                },
                fail: () => {
                  uni.reLaunch({ url: "/pages/index/index" });
                },
              });
            }
            return;
          }

          this.pollTimer = setTimeout(loop, this.interval);
        } catch (err) {
          console.error(this.$t("api_error"), err);
          clearTimeout(this.pollTimer);
          this.pollTimer = null;
          uni.hideLoading();
          this.isPolling = false;
          this.pollingRetryCount = 0; // 错误后重置重试计数
          this.pollCount++;
        }
      };
      loop();
    },
    showPoseGuide() {
      this.confirm();
      uni.showModal({
        title: this.$t("zhen.pose_guide_title"),
        content: this.$t("zhen.pose_guide_content"),
        showCancel: false,
      });
    },
    retakeMultiPhotos() {
      this.pageState = "camera";
      this.resetWorkflowState();
      this.$nextTick(() => this.initCamera());
    },
    skipOptionalPhotos() {
      if (!this.canSkip) return;
      this.capturedPhotos.push({ path: null });
      // Add a null placeholder for the skipped photo

      // Move to the next step
      this.currentStepIndex++;

      // Check if the workflow is complete after skipping
      if (this.currentStepIndex >= this.currentWorkflow.steps.length) {
        this.stopCamera();
        this.pageState = "multiConfirm";
      } else {
        // If not complete, prepare for the next step (e.g., right face)
        uni.showToast({
          title: this.$t("zhen.please_prepare", { label: this.currentStepConfig.label }),
          icon: "none",
          duration: 1500,
        });
      }
    },
    async confirmMultiPhotos() {
      if (this.isPolling) return; // 如果正在轮询，防止重复点击
      uni.showLoading({ title: this.$t("zhen.uploading") });

      try {
        const photosToUpload = this.capturedPhotos.filter((p) => p.path !== null);
        const uploadPromises = photosToUpload.map((photo) => {
          const originalIndex = this.capturedPhotos.findIndex((p) => p.path === photo.path);
          const stepLabel = this.currentWorkflow.steps[originalIndex].label;

          return upload({
            url: "/api/v1/hospital/upload",
            filePath: photo.path,
            name: "file",
            showLoading: false,
            formData: { bizType: `${this.cameraSource}-${stepLabel}` },
          });
        });

        const uploadResults = await Promise.all(uploadPromises);
        const photoUrls = uploadResults.map((res) => {
          if (res.result && res.result.url) {
            return res.result.url;
          }
          throw new Error(this.$t("zhen.photo_upload_fail"));
        });

        uni.hideLoading();
        uni.showLoading({ title: this.$t("zhen.analyzing_smart") });

        let analysisRes = null;
        let params = {};

        if (this.cameraSource === "tongue") {
          params = {
            tongueFrontImg: photoUrls[0],
            tongueBottomImg: photoUrls[1],
            user_id: this.userInfo.id,
          };
          this.isPolling = true;
          const createRes = await createTonguet(params);
          if (createRes && createRes.code === 200 && createRes.result) {
            this.appoint_no = createRes.result.appoint_no; // 保存任务编号
            // 检查是否有问卷
            if (createRes.result.subject && createRes.result.subject.length > 0) {
              // 有问卷，进入问卷流程
              this.questionnaireData = {
                tongue_id: createRes.result.tongue_id,
                id: createRes.result.id,
                questions: createRes.result.subject,
              };
              this.initializeAnswers();
              this.pageState = "questionnaire";
              uni.hideLoading(); // 进入问卷前隐藏"智能分析中"
            } else {
            }
          } else {
            uni.hideLoading();
            uni.showToast({ title: createRes.message || this.$t("zhen.create_task_fail"), icon: "none" });
            this.isPolling = false;
          }
        } else if (this.cameraSource === "face") {
          this.isPolling = true;
          params = {
            faceImgPath: photoUrls[0],
            faceLeftImgPath: photoUrls[1],
            faceRightImgPath: photoUrls[2],
            user_id: this.userInfo.id,
          };
          const createFaceRes = await createFaceDiagnosis(params);

          if (createFaceRes.code === 200 && createFaceRes.result && createFaceRes.result.subject) {
            this.questionnaireData = {
              faceId: createFaceRes.result.faceId,
              id: createFaceRes.result.id,
              questions: createFaceRes.result.subject,
            };
            this.initializeAnswers();
            this.pageState = "questionnaire";
          } else {
            uni.showToast({ title: createFaceRes.message, icon: "none" });
            this.isPolling = false;
            throw new Error(createFaceRes.message || this.$t("zhen.face_service_error"));
          }
        } else {
          throw new Error(this.$t("zhen.unknown_type", { type: this.cameraSource }));
        }

        if (analysisRes && analysisRes.code === 200 && analysisRes.result) {
          if (this.cameraSource === "tongue") {
            this.analysisResult = analysisRes.result;
            this.analysisResult.userInfo = this.userInfo;
          } else if (this.cameraSource === "face") {
            this.analysisResult = {
              picUrl: analysisRes.result.report_image_url || photoUrls[0],
            };
          }
          this.pageState = "results";
        }
      } finally {
        uni.hideLoading();
      }
    },
    initializeAnswers() {
      this.answers = this.questionnaireData.questions.reduce((acc, q) => {
        acc[q.subjectId] = null;
        return acc;
      }, {});
    },
    selectAnswer(questionId, answerCode) {
      if (this.isAnswering) return;
      this.answers[questionId] = answerCode;
      if (!this.areAllQuestionsAnswered) return;

      if (this.cameraSource === "face") {
        this.submitSingleAnswer();
      } else {
        this.submitSingleAnswerByTongue();
      }
    },
    handleAgeInput(questionId) {
      if (this.isAnswering) return;
      const age = this.answers[questionId];
      if (!age || age <= 0) {
        uni.showToast({ title: this.$t("zhen.please_input_valid_age"), icon: "none" });
        return;
      }

      if (!this.areAllQuestionsAnswered) return;
      if (this.cameraSource === "face") {
        this.submitSingleAnswer();
      } else {
        this.submitSingleAnswerByTongue();
      }
    },
    async submitSingleAnswer() {
      this.isAnswering = true;
      uni.showLoading({ title: this.$t("zhen.please_wait"), mask: true });
      const answerPayload = this.questionnaireData.questions.map((question) => {
        return {
          subjectId: String(question.subjectId),
          answerCode: String(this.answers[question.subjectId]),
        };
      });
      try {
        const payload = {
          id: this.questionnaireData.id,
          faceId: this.questionnaireData.faceId,
          answer: answerPayload, // 使用构建好的答案数组
        };

        const res = await answerQuestion(payload);
        if (res.code === 200 && res.result) {
          if (res.result.isFinalResult === "1") {
            await this.fetchFinalFaceResult();
          } else if (res.result.subject && res.result.subject.length > 0) {
            this.questionnaireData.questions = res.result.subject;
            this.initializeAnswers();
          } else {
            await this.fetchFinalFaceResult();
          }
        } else {
          throw new Error(res.message || this.$t("zhen.submit_answer_fail"));
        }
      } catch (err) {
        uni.showToast({ title: err.message, icon: "none" });
      } finally {
        this.isAnswering = false;
        uni.hideLoading();
      }
    },
    async submitSingleAnswerByTongue() {
      this.isAnswering = true;
      uni.showLoading({ title: this.$t("zhen.please_wait"), mask: true });

      const answerPayload = this.questionnaireData.questions.map((question) => {
        return {
          subjectId: String(question.subjectId),
          answerCode: String(this.answers[question.subjectId]),
        };
      });
      try {
        const payload = {
          tongue_id: this.questionnaireData.tongue_id,
          appoint_no: this.appoint_no,
          answer: answerPayload, // 使用构建好的答案数组
        };

        const res = await answerTongueQuestion(payload);
        if (res.code === 200 && res.result) {
          if (res.result.isFinalResult === "1") {
            this.startPollingForTongueResult();
          } else if (res.result.subject && res.result.subject.length > 0) {
            this.questionnaireData.questions = res.result.subject;
            this.initializeAnswers();
          } else {
            // 没有问卷，直接开始轮询结果
            this.startPollingForTongueResult();
          }
        } else {
          throw new Error(res.message || this.$t("zhen.submit_answer_fail"));
        }
      } catch (err) {
        uni.showToast({ title: err.message, icon: "none" });
      } finally {
        this.isAnswering = false;
        uni.hideLoading();
      }
    },
    async fetchFinalFaceResult() {
      uni.showLoading({ title: this.$t("zhen.generating_report") });
      try {
        const finalRes = await getFinalFaceResult(this.questionnaireData.faceId);
        if (finalRes.code === 200 && finalRes.result) {
          this.analysisResult = { ...finalRes.result, userInfo: this.userInfo };
          this.pageState = "results";
        } else {
          throw new Error(finalRes.message || this.$t("zhen.get_report_fail"));
        }
      } catch (err) {
        uni.showToast({ title: err.message, icon: "none" });
      } finally {
        uni.hideLoading();
      }
    },
    async startPollingForTongueResult() {
      if (this.pollingRetryCount === 0) {
        this.pollCount = 0; // 初次轮询时重置计数
      }
      await new Promise((resolve) => setTimeout(resolve, 300));
      uni.showLoading({ title: this.$t("zhen.generating_report"), mask: true });

      clearTimeout(this.pollTimer);
      this.isPolling = true;

      const loop = async () => {
        try {
          const statusRes = await checkTongueStatus(this.appoint_no);
          if (statusRes.result && statusRes.result.status === "000") {
            clearTimeout(this.pollTimer);
            uni.hideLoading();
            this.pollTimer = null;
            this.pollingRetryCount = 0; // [新增] 成功后重置重试计数
            const finalResultRes = await getTongueResult(this.appoint_no);
            if (finalResultRes && finalResultRes.code === 200 && finalResultRes.result) {
              this.analysisResult = finalResultRes.result;
              this.analysisResult.userInfo = this.userInfo;
              this.pageState = "results";
            } else {
              throw new Error(finalResultRes.message || this.$t("zhen.get_diagnosis_report_fail"));
            }
            this.isPolling = false;
            return;
          }
          if (statusRes.result && statusRes.result.status === "101") {
            clearTimeout(this.pollTimer);

            this.isPolling = false;
            this.pollingRetryCount = 0; //  失败后重置重试计数
            uni.showToast({ title: statusRes.result.msg, icon: "none" });
            return;
          }

          this.pollCount++;
          if (this.pollCount >= this.maxPollCount) {
            clearTimeout(this.pollTimer);
            this.isPolling = false; // [MODIFIED] 成功后重置按钮状态

            if (this.pollingRetryCount >= 1) {
              uni.showModal({
                title: this.$t("common.confirm"),
                content: this.$t("zhen.analysis_still_in_progress"),
                showCancel: false, // 关键：隐藏取消按钮
                confirmText: this.$t("zhen.back_to_home"),
                success: (res) => {
                  if (res.confirm) {
                    uni.hideLoading();
                    // 用户点击“知道了”，返回首页
                    setTimeout(() => {
                      uni.reLaunch({ url: "/pages/index/index" });
                    }, 300);
                  }
                },
                fail: () => {
                  uni.hideLoading();

                  setTimeout(() => {
                    uni.reLaunch({ url: "/pages/index/index" });
                  }, 300);
                },
              });
            } else {
              // 首次超时，弹出模态框
              uni.showModal({
                title: this.$t("common.confirm"),
                content: this.$t("zhen.analysis_timeout"),
                confirmText: this.$t("zhen.continue_waiting"),
                cancelText: this.$t("zhen.check_later"),
                success: (res) => {
                  if (res.confirm) {
                    // 用户选择“继续等待”
                    this.pollingRetryCount++; // 增加重试计数
                    this.pollCount = 0; // 重置当前轮询次数
                    this.isPolling = true; // 重新启用按钮
                    uni.showLoading(); // 重新显示加载
                    this.pollTimer = setTimeout(loop, this.interval); // 继续轮询
                  } else if (res.cancel) {
                    uni.hideLoading();
                    // 用户选择“稍后去历史记录查看”
                    uni.reLaunch({
                      url: "/pages/index/index",
                    });
                  }
                },
                fail: (err) => {
                  console.error("Modal failed:", err);
                  uni.hideLoading();
                  uni.reLaunch({
                    url: "/pages/index/index",
                  });
                },
              });
            }
            return;
          }
          this.pollTimer = setTimeout(loop, this.interval);
        } catch (err) {
          // console.error('轮询过程中发生错误:', err)
          clearTimeout(this.pollTimer);
          this.isPolling = false;
          this.pollingRetryCount = 0; // [新增] 错误后重置重试计数
          uni.hideLoading();
          uni.showToast({ title: err.message || this.$t("zhen.analysis_error"), icon: "none" });
        }
      };
      setTimeout(() => {
        loop();
      }, 150);
    },
    restart() {
      this.analysisResult = { picUrl: "", acupointList: [], linkTo: {} };
      this.pageState = "camera";
      this.resetWorkflowState();
      clearTimeout(this.pollTimer);
      this.pollTimer = null;
      this.$nextTick(() => this.initCamera());
    },
  },
};
</script>

<style lang="scss" scoped>
.container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100vw;
  background-color: #000;
  overflow: hidden;
}

/* [MODIFIED] Added padding-bottom to reserve space for the fixed controls */
.camera-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  padding-bottom: 160px; /* This should match the height of .bottom-controls */
  box-sizing: border-box; /* Ensures padding is included in the height calculation */
}

.camera-wrapper {
  flex: 1;
  position: relative;
  overflow: hidden;
  background-color: #000;
  display: flex;
  justify-content: center;
  align-items: center;
}
.camera-canvas,
.preview-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.camera-prompt {
  position: absolute;
  top: 20px;
  left: 0;
  right: 0;
  z-index: 5;
  text-align: center;
  pointer-events: none; /* 让下层元素可以被点击 */
}

.prompt-text {
  color: #fff;
  padding: 6px 15px;
  font-size: 14px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

.guide-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0.8;
}

/* [MODIFIED] Changed to position: fixed */
.bottom-controls {
  position: fixed; /* Changed from 'relative' to 'fixed' */
  bottom: 0;
  left: 0;
  right: 0;

  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
  padding-top: 10px;
  z-index: 10;
  height: 160px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
  transition: all 0.2s ease-in-out;
}

.part-selector {
  width: 100%;
  margin-bottom: 10px;
  overflow: visible;
}
.scroll-view {
  white-space: nowrap;
  width: 100%;
  text-align: center;
}
.part-item {
  display: inline-block;
  color: #ccc;
  padding: 8px 15px;
  font-size: 15px;
  transition: all 0.2s ease;
}
.part-item.active {
  color: #4cd964;
  font-weight: bold;
  transform: scale(1.15);
}
.action-buttons {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  width: 100%;
  padding: 5px 0;
  box-sizing: border-box;
  position: relative;
}
.center-shutter {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
}
.right-switch {
  position: absolute;
  right: 32px;
  z-index: 2;
}
.button-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: white;
  flex: 1;
  text-align: center;
  cursor: pointer;
}
.icon-placeholder {
  width: 32px;
  height: 32px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  color: #fff;
}
.btn-text {
  font-size: 13px;
  margin-top: 5px;
  color: #fff;
}
.btn-text.primary {
  color: #4cd964;
  font-weight: bold;
}
.shutter-button-wrapper {
  width: 70px;
  height: 70px;
  border-radius: 50%;
  background-color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 4px;
  box-sizing: border-box;
  cursor: pointer;
  transition: transform 0.1s ease;
}
.shutter-button-wrapper:active {
  transform: scale(0.95);
}
.shutter-button-wrapper.disabled {
  opacity: 0.5;
  pointer-events: none;
}
.shutter-button {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: #fff;
  border: 3px solid #000;
  box-sizing: border-box;
}
.confirm-actions {
  display: flex;
  justify-content: space-around;
  align-items: center;
  width: 100%;
  /*
      The height is now controlled by the parent .bottom-controls,
      so min-height might not be strictly necessary but is harmless.
    */
  min-height: 95px;
  padding-bottom: 10px;
}
.confirm-actions .button-wrapper .btn-text {
  font-size: 17px;
}

.confirm-page-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100vw;
  /* This padding is for the footer inside this specific container */
  padding-bottom: 160rpx;
  background-color: #f7f8fa;
}

.confirm-page-header {
  text-align: center;
  padding: 12px 0;
  font-size: 18px;
  font-weight: 500;
  background-color: #fff;
  position: relative;
  border-bottom: 1px solid #ebedf0;
  flex-shrink: 0;
}

.confirm-scroll-view {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  box-sizing: border-box;
}

.scroll-content-wrapper {
  padding: 16px;
  box-sizing: border-box;
}
.photo-item {
  background-color: #fff;
  border-radius: 8px;
  padding: 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.photo-label {
  font-size: 16px;
  color: #323233;
}

.photo-preview {
  width: 80px;
  height: 80px;
  border-radius: 6px;
  background-color: #eee;
}

.confirm-page-footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  gap: 24rpx;
  padding: 24rpx 30rpx;
  background-color: #fff;
  border-top: 1rpx solid #f0f0f0;
  padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
  padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
  z-index: 100;
}
.footer-btn {
  flex: 1;
  height: 44px;
  line-height: 44px;
  border-radius: 22px;
  font-size: 16px;
  margin: 0;
}
.retake-btn {
  background-color: #f2f3f5;
  color: #323233;
  border: 1px solid #ebedf0;
}
.confirm-btn {
  background-color: #007aff;
  color: #fff;
}

.questionnaire-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100vw;
  background-color: #afa0ec;
  padding: 30rpx;
  box-sizing: border-box;
}

.questionnaire-header {
  padding: 20rpx 0 40rpx;
  color: #fff;
  text-align: left;
  .header-text {
    font-size: 32rpx;
    line-height: 1.5;
  }
}

.questionnaire-scroll {
  flex: 1;
  height: 0;
}

.question-list.answering {
  pointer-events: none;
  opacity: 0.7;
}

.question-card {
  background-color: #fff;
  border-radius: 20rpx;
  padding: 40rpx 30rpx;
  margin-bottom: 30rpx;
}

.question-title-wrapper {
  display: flex;
  align-items: center;
  margin-bottom: 40rpx;
  .question-title {
    font-size: 34rpx;
    font-weight: 600;
    color: #333;
  }
}

.answer-options {
  display: flex;
  flex-direction: column;
  gap: 30rpx;
}

.age-input {
  width: 100%;
  height: 90rpx;
  line-height: 90rpx;
  text-align: center;
  background-color: #fff;
  border: 1px solid #e0e0e0;
  border-radius: 45rpx;
  font-size: 32rpx;
  color: #333;
  box-sizing: border-box;
}

.answer-btn {
  width: 100%;
  height: 90rpx;
  line-height: 90rpx;
  text-align: center;
  background-color: #fff;
  color: #333;
  border: 1px solid #e0e0e0;
  border-radius: 45rpx;
  font-size: 32rpx;
  transition: all 0.2s;

  &.active {
    background-color: #8c6df6;
    color: #fff;
    border-color: #8c6df6;
    font-weight: 500;
  }
}
.skip-prompt-box {
  position: absolute;
  bottom: 60px;
  left: 10%;
  right: 10%;
  background-color: rgba(40, 40, 40, 0.7);
  color: #ffffff;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 14px;
  z-index: 6;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;

  .skip-highlight {
    color: #ffd966;
  }
}
</style>
